home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol06 / 03 / winedd / feeder.c < prev    next >
Text File  |  1991-05-01  |  10KB  |  293 lines

  1. /* ----------------------------- FEEDER.C ----------------------------------
  2.                      Embedded Device Driver Application.
  3.                       Feeder (device simulator) module.
  4.  
  5.                            Spark Software Inc. 1991.
  6.    ------------------------------------------------------------------------- */
  7.  
  8. /* The following is an intentionally empty definition; this is used to tell */
  9. /* the compiler that we wish to have the global variables in "globals.h"    */
  10. /* declared in this source module and only defined in all others.           */
  11. #define PUBLIC
  12.  
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <memory.h>
  16. #include <dos.h>
  17. #include "dprivate.h"
  18. #include "device.h"
  19. #include "intnum.h"
  20. #include "logmsg.h"
  21. #include "fdefs.h"
  22.  
  23.  
  24. /* Public function prototypes. */
  25. PUBLIC int      PASCAL WinMain( HANDLE , HANDLE , LPSTR , int );
  26. PUBLIC LONG FAR PASCAL FeederWndProc( HWND , WORD , WORD , LONG );
  27.  
  28. /* Private function prototypes. */
  29. PRIVATE BOOL  NEAR PASCAL Init( HANDLE );
  30. PRIVATE LONG  NEAR PASCAL DoTimer( VOID );
  31.  
  32. /* Private data object declarations. */
  33. PRIVATE BOOL  bEnded;                   /* Logger defunct?                */
  34. PRIVATE BYTE  szAppName[ ] = APP_NAME;  /* Application name.              */
  35. PRIVATE BYTE  szClass[ ] = APP_CLASS;   /* Window class name.             */
  36. PRIVATE BYTE      szString[ 81 ];       /* Generic text buffer.               */
  37. PRIVATE WORD      wCharWidth , wCharHeight;     /* Font information.          */
  38. PRIVATE HANDLE    hInst , hPrevInst;    /* Handles to program instances.      */
  39. PRIVATE HWND      hWndMaster;           /* Handle of our master window.       */
  40.  
  41.  
  42. PUBLIC int PASCAL WinMain( hInstance , hPrevInstance , lpszCmdLine , nCmdShow )
  43. HANDLE hInstance , hPrevInstance;
  44. LPSTR  lpszCmdLine;
  45. int    nCmdShow;
  46. {
  47.     DWORD dwThisTime , dwPrevTime;
  48.     MSG   Msg;
  49.  
  50.  
  51.     /* Call initialization procedure if this is the first instance. */
  52.     if( !hPrevInstance && !Init( hInstance ) )
  53.         return 0;
  54.  
  55.     if( hPrevInstance )
  56.     {
  57.         /* See if the top-level window of this app still exists. */
  58.         GetInstanceData( hPrevInstance , (PSTR)&hWndMaster , sizeof hWndMaster );
  59.  
  60.         if( IsWindow( hWndMaster ) )
  61.         {
  62.             /* We won't allow more than one invocation of this program. */
  63.             sprintf( szString , "%s already active." , APP_NAME );
  64.             MessageBox( GetFocus( ) , (LPSTR)szString , (LPSTR)szAppName , MB_OK | MB_ICONHAND );
  65.             return 0;
  66.         }
  67.     }
  68.  
  69.     /* Create our top-level (i.e., master) window. */
  70.     hWndMaster = CreateWindow(
  71.           (LPSTR)szClass                        ,
  72.           (LPSTR)szAppName                      ,
  73.           WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN ,
  74.           CW_USEDEFAULT                         ,
  75.           0                                     ,
  76.           CW_USEDEFAULT                         ,
  77.           0                                     ,
  78.           (HWND)NULL                            ,
  79.           (HMENU)NULL                           ,
  80.           hInstance                             ,
  81.           (LPSTR)NULL
  82.         );
  83.  
  84.     hInst     = hInstance;
  85.     hPrevInst = hPrevInstance;
  86.  
  87.     /* Show the window. */
  88.     ShowWindow( hWndMaster , nCmdShow );
  89.  
  90.     /* Process messages from our queue. */
  91.     dwThisTime = dwPrevTime = GetTickCount( );
  92.     while( TRUE )
  93.     {
  94.         if( PeekMessage( (LPMSG)&Msg , NULL , 0 , 0 , PM_REMOVE ) )
  95.         {
  96.             if( Msg.message == WM_QUIT )
  97.             {
  98.                 return (int)Msg.wParam;
  99.             }
  100.  
  101.             TranslateMessage( (LPMSG)&Msg );
  102.             DispatchMessage(  (LPMSG)&Msg );
  103.         }
  104.  
  105.         /* NOTE: working in this part of the message loop allows */
  106.         /* us to process input when we have 0 or more messages.  */
  107.         if( dwPrevTime + FEED_TIMER_INTERVAL <= ( dwThisTime = GetTickCount( ) ) )
  108.         {
  109.             /* Feed the device driver. */
  110.             DoTimer( );
  111.             dwPrevTime = dwThisTime;
  112.         }
  113.     }
  114.  
  115. }/* WinMain( ) */
  116.  
  117.  
  118. /* Procedure called when the application is loaded for the first time */
  119. PRIVATE BOOL NEAR PASCAL Init( hInstance )
  120. HANDLE hInstance;
  121. {
  122.     WNDCLASS Class;
  123.  
  124.  
  125.     /* Register the window class. */
  126.     Class.hCursor       = LoadCursor( NULL, IDC_ARROW );
  127.     Class.hIcon         = LoadIcon( hInstance , MAKEINTRESOURCE( APPICON ) );
  128.     Class.lpszMenuName  = (LPSTR)NULL;
  129.     Class.lpszClassName = (LPSTR)szClass;
  130.     Class.hbrBackground = GetStockObject( WHITE_BRUSH );
  131.     Class.hInstance     = hInstance;
  132.     Class.style         = CS_HREDRAW | CS_VREDRAW;
  133.     Class.lpfnWndProc   = FeederWndProc;
  134.     Class.cbClsExtra    = 0;
  135.     Class.cbWndExtra    = 0;
  136.  
  137.     if( !RegisterClass( (LPWNDCLASS)&Class ) )
  138.         /* Initialization failed. */
  139.         return FALSE;
  140.  
  141.     return TRUE;
  142.  
  143. }/* Init( ) */
  144.  
  145.  
  146. PUBLIC LONG FAR PASCAL FeederWndProc( hWnd , wMessage , wParam , lParam )
  147. HWND hWnd;
  148. WORD wMessage;
  149. WORD wParam;
  150. LONG lParam;
  151. {
  152.     PRIVATE WORD wLoggerDefunctMsg;
  153.  
  154.  
  155.     switch( wMessage )
  156.     {
  157.     case WM_CREATE:
  158.         bEnded = FALSE;
  159.         wLoggerDefunctMsg = RegisterWindowMessage( LOGGER_DEFUNCT_MSG );
  160.         return (LONG)1;
  161.  
  162.     case WM_DESTROY:
  163.         PostQuitMessage( 0 );
  164.         return (LONG)1;
  165.  
  166.     default:
  167.         if( wMessage == wLoggerDefunctMsg )
  168.         {
  169.             /* No interrupt handler; LOGGER has terminated. */
  170.             DestroyWindow( hWndMaster );
  171.             bEnded = TRUE;
  172.             return (LONG)1;
  173.         }
  174.         else
  175.         {
  176.             return DefWindowProc( hWnd , wMessage , wParam , lParam );
  177.         }
  178.     }
  179.  
  180. }/* FeederWndProc( ) */
  181.  
  182.  
  183. PRIVATE LONG NEAR PASCAL DoTimer( )
  184. {
  185.     PRIVATE WORD wIndex;
  186.  
  187. #   ifdef INTERRUPT_DEVICE  /* Feed the device via interrupt. */
  188.  
  189. #   ifndef C6_ASM           /* C 6.0 compiler supports _asm keyword. */
  190.  
  191.     union  REGS  Regs;
  192.     struct SREGS SRegs;
  193.  
  194. #   endif /* C6_ASM */
  195.  
  196. #   endif /* INTERRUPT_DEVICE */
  197.  
  198.  
  199.     /* Have we destroyed our window? */
  200.     if( bEnded )
  201.     {
  202.         /* No interrupt handler; LOGGER has terminated. */
  203.         return (LONG)1;
  204.     }
  205.  
  206.     /* Before invoking the interrupt handler, place a counter into */
  207.     /* AX so that we know data is being transferred properly.      */
  208.  
  209. #   ifdef INTERRUPT_DEVICE  /* Feed the device via interrupt. */
  210.  
  211. #   ifdef C6_ASM            /* C 6.0 compiler supports _asm keyword. */
  212.  
  213.     /* Set up the machine registers, execute an INT and notify the user. */
  214.     _asm
  215.     {
  216.         push    ax          ; Save register state.
  217.         push    bx          ;
  218.         push    cx          ;
  219.         push    dx          ;
  220.         push    si          ;
  221.         push    di          ;
  222.  
  223.         mov     ax , 0      ; Prepare to
  224.         lahf                ; get the flags and
  225.         push    ax          ; put them on the stack too.
  226.  
  227.         mov     ax , wIndex ; Set up registers for the interrupt.
  228.         mov     bx , 0      ;
  229.         mov     cx , 0      ;
  230.         mov     dx , 0      ;
  231.         mov     si , 0      ;
  232.         mov     di , 0      ;
  233.         int     INTNUM      ; Do the interrupt!
  234.  
  235.         mov     ax , 0      ;
  236.         push    ax
  237.         call    MessageBeep ; Beep.
  238.  
  239.         pop     ax          ; Pop the flags and
  240.         sahf                ; restore them.
  241.  
  242.         pop     di          ; Restore register state.
  243.         pop     si          ;
  244.         pop     dx          ;
  245.         pop     cx          ;
  246.         pop     bx          ;
  247.         pop     ax          ;
  248.     }
  249.  
  250. #   else /* C6_ASM */   /* V5.1 C compiler supports int86x only. */
  251.  
  252.     /* NOTE:  C 5.X doesn't work with Windows 3.0 here, because int86x( ) */
  253.     /* writes the INT instruction to the stack segment and executes       */
  254.     /* it there (the only alternative would be to have a large "switch    */
  255.     /* statment" in int86x( ) because the argument to INT must be a       */
  256.     /* constant).  When int86x( ) then tries to run the code written on   */
  257.     /* the stack segment, a GP fault occurs because CODE SEGMENTS ARE     */
  258.     /* READ-ONLY.  If you must write code like this using C 5.1 and       */
  259.     /* Windows 3.0, you must use MASM.                                    */
  260.  
  261.     Regs.x.ax = wIndex;
  262.     Regs.x.bx = Regs.x.cx = Regs.x.dx = Regs.x.si = Regs.x.di = 0;
  263.     Regs.x.cflag = 0;
  264.     segread( &SRegs );
  265.     int86x( INTNUM , &Regs ,&Regs , &SRegs );
  266.     MessageBeep( 0 );
  267.  
  268. #   endif /* C6_ASM */
  269.  
  270. #   else /* INTERRUPT_DEVICE */ /* Call the interrupt handler directly. */
  271.  
  272.     /* NOTE: C DOES NOT guarantee us that the first 13 parameters passed    */
  273.     /* to a function declared with the _interrupt keyword (or the alias     */
  274.     /* interrupt) will be received as passed.  The use of the _interrupt    */
  275.     /* keyword directs the compiler to load those parameters directly from  */
  276.     /* the machine registers before calling the function, ignoring what     */
  277.     /* was passed if the function was called directly from an application.  */
  278.     /* Arguments to be passed by a direct call should be appended to the    */
  279.     /* parameter list (i.e. AFTER all 13 register parameters).              */
  280.     INTHANDLER( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , wIndex , 0 , 0 , 0 );
  281.  
  282. #   endif /* INTERRUPT_DEVICE */
  283.  
  284.     /* Flash the application's icon. */
  285.     FlashWindow( hWndMaster , TRUE );
  286.     FlashWindow( hWndMaster , FALSE );
  287.     wIndex++;
  288.     return (LONG)1;
  289.  
  290. }/* DoTimer( ) */
  291.  
  292. /* EOF */
  293.